home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------
- ; MODULE XPOLYGON
- ;
- ; Filled Triangle function for all MODE X 256 Color resolutions
- ;
- ; Compile with Tasm.
- ; C callable.
- ;
- ; ****** XLIB - Mode X graphics library ****************
- ; ****** ****************
- ; ****** Written By Themie Gouthas ****************
- ;
- ; This module is based on code developed by Steve Dollind for his
- ; XSPACE game.
- ; Copyright (C) 1992 Steven Dollins -- sdollins@uiuc.edu
- ;
- ;
- ; egg@dstos3.dsto.gov.au
- ; teg@bart.dsto.gov.au
- ;-----------------------------------------------------------------------
- include xlib.inc
- include xpolygon.inc
-
- .data
- ; Plane masks for clipping left and right edges of rectangle.
- LeftClipPlaneMask db 00fh,00eh,00ch,008h
- RightClipPlaneMask db 00fh,001h,003h,007h
-
- .code
-
-
- ;-----------------------------------------------------------------------
- ; void HLineClipR
- ;
- ; Draws a horizontal line from (X1, Y) to (X2, Y).
- ; Uses Watcom Parameter passing convention in registers
- ;
- ; X1 in AX
- ; X2 in DX
- ; Y in CX
- ; Color in BX
- ; PageOffset in DI
- ;
- ; By Themie Gouthas - Adapted from x_fill_rect.
- ;-----------------------------------------------------------------------
- proc _HLineClipR near
- push di
- cmp dx,ax ; if (X2 < X1) then assume no line
- jl @@Invisible ; is visible
-
- cmp cx,[_TopClip] ; if (Y < TopClip) then no line
- jl @@Invisible
-
- cmp cx,[_BottomClip] ;if (Y > BottomClip) then no line
- jg @@Invisible
-
- mov di,[_RightClip] ;convert RightClip to pixel coords
- sal di,2
- cmp ax,di ; if (X1 > RightClip) then no line
- jg @@Invisible
-
- cmp dx,di ; if (X2 > RightClip) then
- jle @@ClipLeft ; X2:=RightClip
- mov dx,di
-
- @@ClipLeft:
- mov di,[_LeftClip] ;convert LeftClip to pixel coords
- sal di,2
- cmp dx,di ; if (X2 < LeftClip) then no line
- jl @@Invisible
-
- cmp ax,di ;if (X1 > LeftClip) then were ready to plot
- jge @@DoLine
-
- mov ax,di ; X1:=LeftClip
- jmp short @@DoLine
-
- @@Invisible:
- pop di
- ret
-
- @@DoLine:
- pop di ; di = PageOffset
- xchg cx,ax ; AX = Y, CX = X1
- mov si,dx ; SI = DX = X2
- mul [_ScrnLogicalByteWidth]
- mov dx,si ; Reset DX to X1 since mul erases DX
- add ax,di
- mov di,cx
- sar di,2 ; Convert to bytes
- add di,ax ; DI->First byte
-
- and si,03h ; look up right edge plane mask
- mov ah,RightClipPlaneMask[si]
- mov si,cx ; look up left edge plane mask
- and si,03h
- mov al,LeftClipPlaneMask[si]
-
- cmp dx,cx ; No harm in being paranoid..
- jle @@Invisible2
-
- xchg cx,dx ;CX=X2, DX=X1
- dec cx
- and dx,not 03h
- sub cx,dx
- js @@Invisible2
- shr cx,2
- jnz @@MasksSet
- and al,ah
- @@MasksSet:
- mov dl,bl ; set BX=Plane Masks, AH=Color
- mov bx,ax
- mov ah,dl
- mov dx,SC_INDEX+1 ;set the Sequence Controller Index to
- mov al,bl
- out dx,al
- mov al,ah
- stosb ; Plot left byte
- dec cx
- js @@Invisible2
- jz @@RightEnd
-
-
- mov al,0fh ; plot middle bytes
- out dx,al
- mov al,ah
- shr cx,1
- rep stosw
- adc cx,cx
- rep stosb
-
-
-
- @@RightEnd:
- mov al,bh ; Plot right byte
- out dx,al
- mov al,ah
- stosb
- @@Invisible2:
- ret
- _HLineClipR endp
-
-
- ;-----------------------------------------------------------------------
- ; void x_triangle( int X0, int Y0, int X1, int Y1,
- ; int X2, int Y2, unsigned Color, unsigned PageOffset );
- ;
- ;
- ; Written by S. Dollins
-
- _x_triangle proc
- ARG X0:word,Y0:word,X1:word,Y1:word,X2:word,Y2:word,Color:word,PageOffset:word
- LOCAL DX01:word, DY01:word, DX02:word, DY02:word, DX12:word, DY12:word, \
- DP01:word, DP02:word, DP12:word, XA01:word, XA02:word, XA12:word=STK
-
- push bp
- mov bp,sp
- sub sp,STK
- push ds es si di ; Save es for polygon routine
-
- mov ax,X0
- mov bx,Y0
- mov cx,X1
- mov dx,Y1
-
- cmp bx,dx ; Y0,Y1
- jl tri_Y0lY1
- je tri_Y0eY1
- xchg ax,cx ; X0,X1
- xchg bx,dx ; Y0,Y1
- tri_Y0lY1:
- cmp dx,Y2 ; Y1,Y2
- jg tri_a
- jmp tri_sorted
- tri_a: xchg cx,X2 ; X1,X2
- xchg dx,Y2 ; Y1,Y2
- cmp bx,dx ; Y0,Y1
- jge tri_b
- jmp tri_sorted
- tri_b: je tri_bot
- xchg ax,cx ; X0,X1
- xchg bx,dx ; Y0,Y1
- jmp tri_sorted
- tri_Y0eY1:
- cmp bx,Y2 ; Y0,Y2
- jl tri_bot
- jg tri_c
- jmp tri_done
- tri_c: xchg ax,X2 ; X0,X2
- xchg bx,Y2 ; Y0,Y2
- jmp tri_sorted
-
- tri_bot:
- cmp ax,cx ; X0,X1
- jl tri_bot_sorted
- jg tri_bot_a
- jmp tri_done
- tri_bot_a:
- xchg ax,cx ; X0,X1
- tri_bot_sorted:
- cmp bx,[_BottomClip]
- jle tri_bot_y0ok
- jmp tri_done
- tri_bot_y0ok:
- mov si,Y2
- cmp si,[_TopClip]
- jge tri_bot_y2ok
- jmp tri_done
- tri_bot_y2ok:
- mov X0,ax
- mov Y0,bx
- mov X1,cx
- mov Y1,dx
-
- mov bx,Y2 ; bx <- Y2
- sub bx,Y0 ; bx <- Y2 - Y0
- mov DY02,bx ; DY02 <- Y2 - Y0
- mov ax,X2 ; ax <- X2
- sub ax,X0 ; ax <- X2 - X0
- mov DX02,ax ; DX02 <- X2 - X0
- mov cx,ax ; cx <- DX02
- cwd ; dx:ax <- DX02
- idiv bx ; ax <- DX02 / DY02
- cmp cx,0
- jge short tri_bot02
- dec ax ; ax <- DX02 / DY02 - 1
- tri_bot02:
- mov XA02,ax ; XA02 <- DX02 / DY02
- imul bx ; ax <- XA02 * DY02
- sub cx,ax ; cx <- DX02 - XA02 * DY02
- mov DP02,cx ; DP02 <- DX02 - XA02 * DY02
-
- mov bx,Y2 ; bx <- Y2
- sub bx,Y1 ; bx <- Y2 - Y1
- mov DY12,bx ; DY02 <- Y2 - Y1
- mov ax,X2 ; ax <- X2
- sub ax,X1 ; ax <- X2 - X1
- mov DX12,ax ; DX12 <- X2 - X1
- mov cx,ax ; cx <- DX12
- cwd ; dx:ax <- DX12
- idiv bx ; ax <- DX12 / DY12
- cmp cx,0
- jge short tri_bot12
- dec ax ; ax <- DX12 / DY12 - 1
- tri_bot12:
- mov XA12,ax ; XA12 <- DX12 / DY12
- imul bx ; ax <- XA12 * DY12
- sub cx,ax ; cx <- DX12 - XA12 * DY12
- mov DP12,cx ; DP12 <- DX12 - XA12 * DY12
-
- mov ax,0 ; PL <- 0
- mov bx,0 ; PS <- 0
- mov cx,Y0 ; Y <- Y0
- mov si,X0
- mov di,X1
- dec di
- tri_bot_loop:
- inc cx ; Y
-
- add ax,DP02 ; PL,DP02
- jle short tri_bot_shortl
- sub ax,DY02 ; PL,DY02
- inc si ; XL
- tri_bot_shortl:
- add si,XA02 ; XL,XA02
-
- add bx,DP12 ; PS,DP12
- jle short tri_bot_shortr
- sub bx,DY12 ; PS,DY12
- inc di ; XS
- tri_bot_shortr:
- add di,XA12 ; XS,XA12
-
- push di ; XS
- push si ; XL
- cmp cx,Y2 ; Y,Y2
- jl short tri_bot_loop
-
- jmp tri_draw_lines
-
-
- tri_sorted:
- cmp bx,[_BottomClip]
- jle tri_y0ok
- jmp tri_done
- tri_y0ok:
- mov si,Y2
- cmp si,[_TopClip]
- jge tri_y2ok
- jmp tri_done
- tri_y2ok:
- mov X0,ax
- mov Y0,bx
- mov X1,cx
- mov Y1,dx
-
- mov bx,dx ; bx <- Y1
- sub bx,Y0 ; bx <- Y1 - Y0
- mov DY01,bx ; DY01 <- Y1 - Y0
- mov ax,X1 ; ax <- X1
- sub ax,X0 ; ax <- X1 - X0
- mov DX01,ax ; DX01 <- X1 - X0
- mov cx,ax ; cx <- DX01
- cwd ; dx:ax <- DX01
- idiv bx ; ax <- DX01 / DY01
- cmp cx,0 ; DX01 ? 0
- jge short tri_psl01
- dec ax ; ax <- DX01 / DY01 - 1
- tri_psl01:
- mov XA01,ax ; XA01 <- DX01 / DY01
- imul bx ; ax <- XA01 * DY01
- sub cx,ax ; cx <- DX01 - XA01 * DY01
- mov DP01,cx ; DP01 <- DX01 - XA01 * DY01
-
- mov bx,Y2 ; bx <- Y2
- sub bx,Y0 ; bx <- Y2 - Y0
- mov DY02,bx ; DY02 <- Y2 - Y0
- mov ax,X2 ; ax <- X2
- sub ax,X0 ; ax <- X2 - X0
- mov DX02,ax ; DX02 <- X2 - X0
- mov cx,ax ; cx <- DX02
- cwd ; dx:ax <- DX02
- idiv bx ; ax <- DX02 / DY02
- cmp cx,0
- jge short tri_psl02
- dec ax ; ax <- DX02 / DY02 - 1
- tri_psl02:
- mov XA02,ax ; XA02 <- DX02 / DY02
- imul bx ; ax <- XA02 * DY02
- sub cx,ax ; cx <- DX02 - XA02 * DY02
- mov DP02,cx ; DP02 <- DX02 - XA02 * DY02
-
- mov bx,Y2 ; bx <- Y2
- sub bx,Y1 ; bx <- Y2 - Y1
- jle short tri_const_computed
- mov DY12,bx ; DY12 <- Y2 - Y1
- mov ax,X2 ; ax <- X2
- sub ax,X1 ; ax <- X2 - X1
- mov DX12,ax ; DX12 <- X2 - X1
- mov cx,ax ; cx <- DX12
- cwd ; dx:ax <- DX12
- idiv bx ; ax <- DX12 / DY12
- cmp cx,0
- jge short tri_psl12
- dec ax ; ax <- DX12 / DY12 - 1
- tri_psl12:
- mov XA12,ax ; XA12 <- DX12 / DY12
- imul bx ; ax <- XA12 * DY12
- sub cx,ax ; cx <- DX12 - XA12 * DY12
- mov DP12,cx ; DP12 <- DX12 - XA12 * DY12
-
- tri_const_computed:
- mov ax,DX01
- imul word ptr DY02
- mov bx,ax
- mov cx,dx ; DX01 * DY02 in cx:bx
-
- mov ax,DX02
- imul word ptr DY01 ; DX02 * DY01 in dx:ax
- cmp cx,dx
- jg tri_pt1rt
- jl tri_pt1lt
- cmp bx,ax
- ja tri_pt1rt
- jb tri_pt1lt
- jmp tri_done
-
- ;------------------------------------
- ; Short sides are on the left
- ;
- tri_pt1lt:
- mov ax,0 ; PL <- 0
- mov bx,0 ; PS <- 0
- mov cx,Y0 ; Y <- Y0
- mov si,X0
- mov di,si
- dec si
- tri_lt_loop:
- inc cx ; Y
-
- add ax,DP02 ; PL,DP02
- jle short tri_lt_shortl
- sub ax,DY02 ; PL,DY02
- inc si ; XL
- tri_lt_shortl:
- add si,XA02 ; XL,XA02
-
- add bx,DP01 ; PS,DP01
- jle short tri_lt_shortr
- sub bx,DY01 ; PS,DY01
- inc di ; XS
- tri_lt_shortr:
- add di,XA01 ; XS,XA01
-
- push si ; XL
- push di ; XS
- cmp cx,Y1 ; Y,Y1
- jl short tri_lt_loop
-
- jmp short tri_lb_start
- tri_lb_loop:
- inc cx ; Y
-
- add ax,DP02 ; PL,DP02
- jle short tri_lb_shortl
- sub ax,DY02 ; PL,DY02
- inc si ; XL
- tri_lb_shortl:
- add si,XA02 ; XL,XA02
-
- add bx,DP12 ; PS,DP12
- jle short tri_lb_shortr
- sub bx,DY12 ; PS,DY12
- inc di ; XS
- tri_lb_shortr:
- add di,XA12 ; XS,XA12
-
- push si ; XL
- push di ; XS
- tri_lb_start:
- cmp cx,Y2 ; Y,Y2
- jl tri_lb_loop
- jmp short tri_draw_lines
-
- ;------------------------------------
- ; short sides are on the right
- ;
- tri_pt1rt:
- mov ax,0 ; PL <- 0
- mov bx,0 ; PS <- 0
- mov cx,Y0 ; Y <- Y0
- mov si,X0
- mov di,si
- dec di
- tri_rt_loop:
- inc cx ; Y
-
- add ax,DP02 ; PL,DP02
- jle short tri_rt_shortl
- sub ax,DY02 ; PL,DY02
- inc si ; XL
- tri_rt_shortl:
- add si,XA02 ; XL,XA02
-
- add bx,DP01 ; PS,DP01
- jle short tri_rt_shortr
- sub bx,DY01 ; PS,DY01
- inc di ; XS
- tri_rt_shortr:
- add di,XA01 ; XS,XA01
-
- push di ; XS
- push si ; XL
- cmp cx,Y1 ; Y,Y1
- jl short tri_rt_loop
-
- jmp short tri_rb_start
- tri_rb_loop:
- inc cx ; Y
-
- add ax,DP02 ; PL,DP02
- jle short tri_rb_shortl
- sub ax,DY02 ; PL,DY02
- inc si ; XL
- tri_rb_shortl:
- add si,XA02 ; XL,XA02
-
- add bx,DP12 ; PS,DP12
- jle short tri_rb_shorts
- sub bx,DY12 ; PS,DY12
- inc di ; XS
- tri_rb_shorts:
- add di,XA12 ; XS,XA12
-
- push di ; XS
- push si ; XL
- tri_rb_start:
- cmp cx,Y2 ; Y,Y2
- jl short tri_rb_loop
-
- ;------------------------------------
- ; Draw the horizontal lines
- ;
-
-
- tri_draw_lines:
-
- mov cx,SCREEN_SEG ;point ES to video segment
- mov es,cx
- mov dx,SC_INDEX ;set the Sequence Controller Index to
- mov al,MAP_MASK ; point to the Map Mask register
- out dx,al
-
-
- line_loop:
- pop ax
- pop dx
- cmp ax,dx
- jg tri_draw_next
- mov bx,Color
- mov cx,Y2
- add dx,2
- mov di,PageOffset
- call _HLineClipR
- tri_draw_next:
- dec word ptr Y2
- dec word ptr DY02
- jnz line_loop
-
- tri_done:
- pop di si es ds
- mov sp,bp
- pop bp
- ret
- _x_triangle endp
-
- ;-----------------------------------------------------------------------
- ; void x_polygon( VERTEX vertices[], int num_vertices,unsigned Color,
- ; unsigned PageOffset );
- ;
- ; Where VERTEX is defined as:
- ;
- ; typedef struct {
- ; int X;
- ; int Y;
- ; } far VERTEX;
- ;
- ;
- ; Written by T. Gouthas
- ;
- ;
- ;
- ; Note: This is just a quick hack of a generalized polygon routine.
- ; The way it works is by splitting up polygons into triangles and
- ; drawing each individual triangle.
- ;
- ; Obviously this is not as fast as it could be, but for polygons of
- ; 4 vertices it should perform quite respectably.
- ;
- ; Warning: Only works for convex polygons (convex polygons are such
- ; that if you draw a line from any two vertices, every point on that
- ; line will be within the polygon)
- ;
- ;
-
- _x_polygon proc
- ARG vertices:dword,numvertices:word,Color:word,PageOffset:word
- LOCAL x0:word,y0:word,tri_count:word=STK
- push bp
- mov bp,sp
- sub sp,STK
- push di si
-
- mov cx,numvertices
- cmp cx,3
- jl @@Done
-
- sub cx,3
- mov tri_count,cx ; Number of triangles to draw
- les di,vertices ; ES:DI -> Vertices
-
- mov ax,es:[di] ; Save first vertex
- mov x0,ax
- mov ax,es:[di+2]
- mov y0,ax
-
- ; Set up permanent parameter stack frame for
- ; triangle parameters
-
- mov ax,PageOffset
- push ax
- mov ax,Color
- push ax
-
- sub sp,12
- mov si,sp
-
- @@NextTriangle:
-
- add di,4
- mov ax,es:[di] ; Vertex 2
- mov ss:[si],ax
- mov ax,es:[di+2]
- mov ss:[si+2],ax
-
- mov ax,es:[di+4] ; Vertex 1
- mov ss:[si+4],ax
- mov ax,es:[di+6]
- mov ss:[si+6],ax
-
- mov ax,x0 ; Vertex 0: The first vertex is
- mov ss:[si+8],ax ; part of every triangle
- mov ax,y0
- mov ss:[si+10],ax
-
- call _x_triangle
- dec tri_count
- jns @@NextTriangle
-
- add sp,16 ; Remove triangle stack frame
-
- @@Done:
- pop si di
- mov sp,bp
- pop bp
- ret
- _x_polygon endp
- end